package yh.platform.core.util;

import cn.hutool.core.lang.UUID;
import com.aliyun.oss.OSS;
import com.aliyun.oss.OSSEncryptionClient;
import com.aliyun.oss.model.OSSObject;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.web.multipart.MultipartFile;
import yh.platform.core.enums.FilePathEnum;

import java.io.*;
import java.util.Date;

/**
 * @author yifei.han
 * @version 1.0
 * @className OssUtil
 * @description
 * @date 2023/3/31
 */
@Slf4j
@Component
public class OssUtil {

    /**
     * 域名
     */
    @Value("${oss.endpoint}")
    private String endpoint;

    /**
     * 存储空间
     */
    @Value("${oss.bucket_name}")
    private String bucketName;

    @Autowired
    private OSS ossClient;

    @Autowired
    private OSSEncryptionClient ossEncryptionClient;

    /**
     * 上传文件（字节数组）
     * @param key
     * @param bytes
     * @return
     */
    public String uploadByteArray(String key, byte[] bytes) {
        return this.uploadInputStream(key, new ByteArrayInputStream(bytes));
    }

    /**
     * 上传文件（输入流）
     * @param key
     * @param inputStream
     * @return
     */
    private String uploadInputStream(String key, InputStream inputStream) {
        ossClient.putObject(bucketName, key, inputStream);
        return this.generatePresignedUrl(key);
    }

    public String uploadInputStreamByFileName(String fileName, Integer fileType, InputStream inputStream) {
        String ossPath = FilePathEnum.getPath(fileType);
        String newFileName = ossPath + "/" + fileName;
        return this.uploadInputStream(newFileName, inputStream);
    }

    /**
     * 上传文件（一般用于服务端上传接口直接调用）
     */
    public String uploadFile(MultipartFile file, Integer fileType) throws IOException {
//        if (FilePathEnum.ID_CARD_FRONT.fileType().equals(fileType)
//                || FilePathEnum.ID_CARD_BACK.fileType().equals(fileType)) {
//            return this.encryptUploadFile(file, fileType);
//        }
        String objectName = this.generateObjectName(file, fileType);
        return this.uploadByteArray(objectName, file.getBytes());
    }

    /**
     * url文件上传
     */
    public String uploadUrlFile(String fileUrl, Integer fileType, String suffix) throws IOException {
        File file = JiujiuctFileUtil.downloadImg(fileUrl, "jiujiuct/temp");
        String ossPath = FilePathEnum.getPath(fileType);
        InputStream inputStream = new FileInputStream(file);
        String newFileName = ossPath + "/" + UUID.randomUUID() + suffix;
        String ossFileUrl = this.uploadInputStream(newFileName, inputStream);
        file.delete();
        return ossFileUrl;
    }

    /**
     * 加密上传文件
     * @param file
     * @param fileType
     * @return
     * @throws IOException
     */
    public String encryptUploadFile(MultipartFile file, Integer fileType) throws IOException {
        InputStream inputStream = file.getInputStream();
        String objectName = this.generateObjectName(file, fileType);
        ossEncryptionClient.putObject(bucketName, objectName, inputStream);
        return this.generatePresignedUrl(objectName);
    }

    /**
     * 加密上传文件
     * @param inputStream
     * @param fileType
     * @Param fileName
     * @return
     * @throws IOException
     */
    public String encryptUploadFile(InputStream inputStream, Integer fileType, String fileName) {
        String ossPath = FilePathEnum.getPath(fileType);
        String newFileName = ossPath + "/" + fileName;
//        String objectName = this.generateObjectName(file, fileType);
        ossEncryptionClient.putObject(bucketName, newFileName, inputStream);
        return this.generatePresignedUrl(newFileName);
    }

    /**
     * url文件解密转 InputStream
     * @param url
     * @return
     */
    public InputStream decryptFile(String url) {
        if (StringUtils.isNotBlank(url)) {
            String http = url.contains("https://") ? "https://" : "http://";
            String bucketNameDomain = http + bucketName +"."+ endpoint + "/";
            String key = url.replace(bucketNameDomain, "");
            OSSObject ossObject = ossEncryptionClient.getObject(bucketName, key);
            return ossObject.getObjectContent();
        }
        return null;
    }

    private String generateObjectName(MultipartFile file, Integer fileType) {
        String ossPath = FilePathEnum.getPath(fileType);
        String originalName = file.getOriginalFilename();
        String suffix = originalName.substring(originalName.lastIndexOf('.'));
        return ossPath + "/" + UUID.randomUUID() + suffix;
    }

    private String generatePresignedUrl(String key) {
        Date expiration = new Date(new Date().getTime() + 1000*60*60*24*365*30);
        // 生成URL
        String url = ossClient.generatePresignedUrl(bucketName, key, expiration).toString();
        int firstChar = url.indexOf('?');
        url = (firstChar > 0) ? url.substring(0, firstChar) : url;
        return url.replace("http://", "https://").replace("-internal", "");
    }


}
